<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class RedemptionCode extends Model
{
    use HasFactory;

    protected $table = 'redemption_codes';

    protected $fillable = [
        'code',
        'name',
        'type',
        'status',
        'expired_at',
        'used_at',
        'used_user_id',
        'used_order_id',
        'metadata'
    ];

    // 日期时间字段
    protected $dates = [
        'expired_at',
        'used_at',
        'created_at',
        'updated_at'
    ];

    // JSON字段处理
    protected $casts = [
        'metadata' => 'array'
    ];

    // 验证metadata结构
    public function validateMetadata()
    {
        if (empty($this->metadata)) {
            return false;
        }

        switch ($this->type) {
            case self::TYPE_TIME_ACCESS:
                return $this->validateTimeAccessMetadata();
            case self::TYPE_DISCOUNT:
                return $this->validateDiscountMetadata();
            case self::TYPE_PRODUCT_EXCHANGE:
                return $this->validateProductExchangeMetadata();
            default:
                return false;
        }
    }

    // 验证时间权限类型的metadata
    private function validateTimeAccessMetadata()
    {
        $metadata = $this->metadata;
        return isset($metadata['days']) && is_numeric($metadata['days']) && $metadata['days'] > 0 &&
               isset($metadata['permission_level']) && is_string($metadata['permission_level']);
    }

    // 验证费用抵扣类型的metadata
    private function validateDiscountMetadata()
    {
        $metadata = $this->metadata;
        if (!isset($metadata['amount']) || !is_numeric($metadata['amount']) || $metadata['amount'] <= 0 ||
            !isset($metadata['currency']) || !is_string($metadata['currency'])) {
            return false;
        }

        // max_discount是可选的，但如果存在必须是数字
        if (isset($metadata['max_discount']) && (!is_numeric($metadata['max_discount']) || $metadata['max_discount'] < 0)) {
            return false;
        }

        // applicable_products是可选的，但如果存在必须是数组
        if (isset($metadata['applicable_products']) && !is_array($metadata['applicable_products'])) {
            return false;
        }

        return true;
    }

    // 验证商品兑换类型的metadata
    private function validateProductExchangeMetadata()
    {
        $metadata = $this->metadata;
        return isset($metadata['product_id']) && is_numeric($metadata['product_id']) && $metadata['product_id'] > 0 &&
               isset($metadata['product_name']) && is_string($metadata['product_name']) &&
               isset($metadata['quantity']) && is_numeric($metadata['quantity']) && $metadata['quantity'] > 0;
    }

    // 获取元数据中的特定字段
    public function getMetadataValue($key, $default = null)
    {
        if (!empty($this->metadata) && isset($this->metadata[$key])) {
            return $this->metadata[$key];
        }
        return $default;
    }

    // 检查是否适用于特定商品
    public function isApplicableToProduct($productId)
    {
        if ($this->type !== self::TYPE_DISCOUNT) {
            return false;
        }

        // 如果没有指定适用商品，则默认适用于所有商品
        if (!isset($this->metadata['applicable_products']) || empty($this->metadata['applicable_products'])) {
            return true;
        }

        return in_array($productId, $this->metadata['applicable_products']);
    }

    // 获取折扣金额
    public function getDiscountAmount($orderAmount = 0)
    {
        if ($this->type !== self::TYPE_DISCOUNT || !$this->validateMetadata()) {
            return 0;
        }

        $discountAmount = $this->metadata['amount'];

        // 检查是否有最大折扣限制
        if (isset($this->metadata['max_discount']) && $discountAmount > $this->metadata['max_discount']) {
            $discountAmount = $this->metadata['max_discount'];
        }

        // 折扣金额不能超过订单金额
        return min($discountAmount, $orderAmount);
    }

    // 获取权限天数
    public function getPermissionDays()
    {
        if ($this->type !== self::TYPE_TIME_ACCESS || !$this->validateMetadata()) {
            return 0;
        }

        return $this->metadata['days'];
    }

    // 获取权限等级
    public function getPermissionLevel()
    {
        if ($this->type !== self::TYPE_TIME_ACCESS || !$this->validateMetadata()) {
            return null;
        }

        return $this->metadata['permission_level'];
    }

    // 获取兑换商品信息
    public function getProductInfo()
    {
        if ($this->type !== self::TYPE_PRODUCT_EXCHANGE || !$this->validateMetadata()) {
            return null;
        }

        return [
            'id' => $this->metadata['product_id'],
            'name' => $this->metadata['product_name'],
            'quantity' => $this->metadata['quantity']
        ];
    }

    // 常量定义
    public const TYPE_TIME_ACCESS = 'time_access';
    public const TYPE_DISCOUNT = 'discount';
    public const TYPE_PRODUCT_EXCHANGE = 'product_exchange';

    public const STATUS_UNUSED = 'unused';
    public const STATUS_USED = 'used';
    public const STATUS_EXPIRED = 'expired';
    public const STATUS_DISABLED = 'disabled';

    // 关联关系
    public function user()
    {
        return $this->belongsTo(WechatUser::class, 'used_user_id');
    }

    public function order()
    {
        return $this->belongsTo(Order::class, 'used_order_id');
    }

    // 检查兑换码是否有效
    public function isValid()
    {
        if ($this->status !== self::STATUS_UNUSED) {
            return false;
        }

        if ($this->expired_at && now()->gt($this->expired_at)) {
            // 如果过期了，更新状态为过期
            $this->status = self::STATUS_EXPIRED;
            $this->save();
            return false;
        }

        return true;
    }

    // 使用兑换码
    public function useCode($userId, $orderId = null)
    {
        if (!$this->isValid() || !$this->validateMetadata()) {
            return false;
        }

        $this->status = self::STATUS_USED;
        $this->used_at = now();
        $this->used_user_id = $userId;
        $this->used_order_id = $orderId;

        return $this->save();
    }

    // 生成时间权限类型兑换码
    public static function generateTimeAccessCode($days, $permissionLevel, $expiredAt = null)
    {
        $code = self::create([
            'code' => self::generateUniqueCode(),
            'type' => self::TYPE_TIME_ACCESS,
            'status' => self::STATUS_UNUSED,
            'expired_at' => $expiredAt,
            'metadata' => [
                'days' => $days,
                'permission_level' => $permissionLevel
            ]
        ]);
        return $code;
    }

    // 生成费用抵扣类型兑换码
    public static function generateDiscountCode($amount, $currency = 'CNY', $maxDiscount = null, $applicableProducts = [], $expiredAt = null)
    {
        $metadata = [
            'amount' => $amount,
            'currency' => $currency
        ];

        if ($maxDiscount !== null) {
            $metadata['max_discount'] = $maxDiscount;
        }

        if (!empty($applicableProducts)) {
            $metadata['applicable_products'] = $applicableProducts;
        }

        $code = self::create([
            'code' => self::generateUniqueCode(),
            'type' => self::TYPE_DISCOUNT,
            'status' => self::STATUS_UNUSED,
            'expired_at' => $expiredAt,
            'metadata' => $metadata
        ]);
        return $code;
    }

    // 生成商品兑换类型兑换码
    public static function generateProductExchangeCode($productId, $productName, $quantity = 1, $expiredAt = null)
    {
        $code = self::create([
            'code' => self::generateUniqueCode(),
            'type' => self::TYPE_PRODUCT_EXCHANGE,
            'status' => self::STATUS_UNUSED,
            'expired_at' => $expiredAt,
            'metadata' => [
                'product_id' => $productId,
                'product_name' => $productName,
                'quantity' => $quantity
            ]
        ]);
        return $code;
    }

    // 生成随机兑换码的静态方法
    public static function generateUniqueCode($length = 16)
    {
        do {
            $code = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, $length);
        } while (self::where('code', $code)->exists());

        return $code;
    }
}